﻿namespace IBTrader.Model
{
    using IBTrader.Charts;
    using IBTrader.Frontend;
    using IBTrader.Indicator;
    using IBTrader.Indicator.Average;
    using IBTrader.Modules.Market;
    using IBTrader.Modules.Strategy;
    using IBTrader.Modules.Tws;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Xml.Serialization;
    using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;

    public class Algos : List<Algo> { }
    public class Algo : NotifyPropertyChanged, IStoreMember
    {
        private string strategy, indicator;
        private float indicatorInterval;
        public Algo() 
        {
            Orders = new AlgoOrders(this);
            OrderSize = 1;
            OrderDuration = new TimeSpan(0, 5, 0);
            TradingStart = new TimeSpan(23, 0, 0);
            TradingEnd = new TimeSpan(21, 0, 0);
            Indicator = typeof(SMA).FullName;
            IndicatorInterval = 100;
            Strategy = typeof(SwingTrader).Name;
        }
        public Algo(Store store) : this()
        {
            this.Store = store; 
            this.Id = store.Algos.Count + 1;
        }
        public int Id { get; set; }
        public OrderingStatus OrderingStatus { get; set; }
        public int OrderSize { get; set; }
        public double PriceOffset { get; set; }
        public double StopLimit { get; set; }
        public OrderType OrderType { get; set; }
        public bool TradingCancelled { get; set; }
        public bool OptimisticSimulation { get; set; }
        public int ContractId { get; set; }
        public int BacklogConfigurationId { get; set; }

        public string Strategy { get { return strategy; } set { strategy = value; Changed(() => Strategy); } }
        public string Indicator { get { return indicator; } set { indicator = value; Changed(() => Indicator); } }
        public float IndicatorInterval { get { return indicatorInterval; } set { indicatorInterval = value; Changed(() => IndicatorInterval); } }

        [XmlIgnore]
        public Store Store { get; set; }
        [XmlIgnore]
        public Contract Contract
        {
            get
            {
                var item = Store.Contracts.SingleOrDefault(a => a.Id == ContractId);
                if (item == null)
                {
                    item = new Contract(Store);
                    ContractId = item.Id;
                    Store.Contracts.Add(item);
                }
                return item;
            }
        }
        [XmlIgnore]
        public BacklogConfiguration BacklogConfiguration
        {
            get
            {
                var item = Store.BacklogConfigurations.SingleOrDefault(a => a.Id == BacklogConfigurationId);
                if (item == null)
                {
                    item = new BacklogConfiguration(Store);
                    BacklogConfigurationId = item.Id;
                    Store.BacklogConfigurations.Add(item);
                }
                return item;
            }
        }
        [XmlIgnore]
        public AlgoOrders Orders { get; private set; }

        [XmlIgnore]
        public TimeSpan OrderDuration { get; set; }
        [XmlIgnore]
        public TimeSpan TradingStart { get; set; }
        [XmlIgnore]
        public TimeSpan TradingEnd { get; set; }

        [XmlElement("OrderDuration")]
        public string OrderDurationTicks { get { return OrderDuration.ToString(); } set { OrderDuration = TimeSpan.Parse(value); } }
        [XmlElement("TradingStart")]
        public string TradingStartTicks { get { return TradingStart.ToString(); } set { TradingStart = TimeSpan.Parse(value); } }
        [XmlElement("TradingEnd")]
        public string TradingEndTicks { get { return TradingEnd.ToString(); } set { TradingEnd = TimeSpan.Parse(value); } }

        public string[] Strategies { get { return new[] { typeof(SwingTrader).Name, typeof(TrendFollower).Name }; } }

        public IEnumerable<object> Indicators
        {
            get
            {
                return Assembly.GetExecutingAssembly().GetTypes().Where(t => !t.IsAbstract && !t.IsNested && t.Namespace != null 
                    && t.Namespace.StartsWith(typeof(SMA).Namespace)).ToArray(); 
                //return
                //    Assembly.GetExecutingAssembly().GetTypes()
                //    .Where(t => t.IsClass && !t.IsAbstract && !t.IsNested && t.Namespace != null && t.Namespace.StartsWith(typeof(IIndicator).Namespace))
                //    .Where(t => t.GetConstructors().Any(c => c.GetParameters().Any(p => p.ParameterType.Equals(typeof(Worker)))))
                //    .Select(t => new { Value = t, Name = t.Name });
            }
        }

        internal void Clear()
        {
            Store.Orders.Clear();
            TradingCancelled = false;
            OrderingStatus = OrderingStatus.None;
            Orders.Clear();
        }
    }
}
